Skip to content

refactor: standardize tsconfig hierarchy, inline handle* functions, improve SvelteKit apps#1542

Merged
braden-w merged 27 commits intomainfrom
opencode/glowing-pixel
Mar 19, 2026
Merged

refactor: standardize tsconfig hierarchy, inline handle* functions, improve SvelteKit apps#1542
braden-w merged 27 commits intomainfrom
opencode/glowing-pixel

Conversation

@braden-w
Copy link
Member

@braden-w braden-w commented Mar 19, 2026

Three loosely-related threads that landed on the same branch during a cleanup pass. They share the same theme: less indirection, tighter types, fewer places to configure the same thing.

tsconfig hierarchy

New three-tier config structure replaces per-package duplication:

tsconfig.base.json
├── tsconfig.base.dom.json   # browser packages
└── tsconfig.base.lib.json   # declaration-emitting packages
  • removes a large amount of duplicated tsconfig boilerplate
  • moves shared options into the right base config instead of repeating them per package
  • keeps per-package overrides only where they are actually needed
  • fixes DOM vs non-DOM assignments based on real runtime usage
  • adds bun-types to the SvelteKit apps for consistency

Honeycrisp refactor

  • splits the larger state surface into smaller modules
  • extracts a few focused components and helpers
  • makes the editor and list flows more data-driven

App and component cleanup

  • inlines thin handle* wrappers into direct event handlers
  • flattens state/action APIs that had grown extra nesting
  • simplifies component flows across opensidian, tab-manager, fuji, honeycrisp, and whispering

Svelte and tooling consistency

  • adds fromKv / fromTable bindings in @epicenter/svelte
  • standardizes Bun typing across the SvelteKit apps
  • updates internal skills and docs to capture the patterns used here

braden-w added 27 commits March 18, 2026 14:01
…d reorganize files

Split the 538-line createNotesState into three focused factories (foldersState,
notesState, viewState) with a clean dependency DAG. Extract workspace schema from
client instantiation, co-locate editor utilities with the Editor component, and
consolidate date utils. All component imports updated to use the split state modules.
…scribing NoteCard, data-driven Editor toolbar

NoteList now takes notes/title/showControls props instead of branching on
view mode internally. NoteCard derives isDeleted from note.deletedAt and
accepts isSelected/onSelect props, dropping the viewState import entirely.
Editor toolbar uses snippets for the 12 repeated button patterns, cutting
150 lines of copy-paste to 20 lines of snippet calls. Sort dropdown is
data-driven via array + {#each}. Svelte skill updated with three new
patterns: prop-first derivation, view-mode branching limit, data-driven
repetitive markup.
…ead folderName branch

Extract FolderMenuItem.svelte from Sidebar per the self-contained component
pattern — each folder row now owns its own rename editing state and delete
confirmation dialog instead of sharing a single dialog managed by the parent.
Sidebar drops from 212 to 93 lines. Also remove the dead isRecentlyDeletedView
branch from viewState.folderName since the parent now passes the title directly.
…inlining rule

Inline 7 single-use functions across 4 components: startRename/cancelRename
in FolderMenuItem, toggleHeading/toggleListType in Editor, handleKeydown in
NoteList and +page. commitRename stays extracted (used 2x: keydown + blur).
Update Svelte skill to replace the narrow 'no handle* functions' rule with
a broader single-use inlining rule: inline by default, keep extracted only
with JSDoc + semantic name. Multi-use functions always stay extracted.
Grep for 'function handle' found 20 handle* functions in .svelte files
across the monorepo. 17 were single-use wrappers adding unnecessary
indirection — inlined at the call site. FileTree.handleKeydown renamed
to navigateFileTree with JSDoc (75-line keyboard nav switch, legitimate
exception). Two skipped: TransformationPickerBody (imperative onMount
listener) and UpdateDialog (30-line download flow).

Apps touched: opensidian (6 files), tab-manager (2), fuji (2),
landing (1). Also adds docs/articles/grep-for-handle-functions.md
explaining the grep command and the smell pattern.
…to @epicenter/svelte

Rename @epicenter/svelte-utils → @epicenter/svelte and add two new
reactive utilities that eliminate boilerplate observer patterns across
all apps.

fromKv wraps a single KV key into a { current } box (mirrors Svelte 5's
fromStore). fromTable returns a SvelteMap with granular per-row updates
via the table observer, replacing the wholesale array re-read pattern.

Migrated 8 files across honeycrisp, fuji, and tab-manager from manual
$state + observe → fromKv/fromTable. All derived arrays cached via
$derived to avoid re-creating on every getter access.

Also standardizes tsconfig lib from ES2022 → ESNext across 12 packages.
….filter())

TC39 Iterator Helpers (Stage 4) are fully typed in TS 5.9 via
lib.esnext.iterator.d.ts. MapIterator extends IteratorObject which
provides .filter(), .map(), .find(), .toArray(), .some(), .every(),
.reduce(), .take(), .drop(), .flatMap() — no spread needed.

Replaces all [...map.values()] patterns with map.values().toArray().
Sort still requires materialization (.toArray().sort()) since sort
needs random access.

Updated svelte skill with iterator helpers guidance.
… table state pattern to Svelte skill

Iterator helpers (.toArray(), .filter(), .find() on IteratorObject) are
a TS/JS language feature — moved to typescript skill where it belongs.

Svelte skill now documents the fromTable → $derived → getter naming
convention: {name}Map → {name} → get {name}(). Consolidated from ~80
lines of mixed TS/Svelte content into ~45 focused lines.
The workspace-api skill covered schema definition thoroughly but said
nothing about reading, writing, or observing data. Added table CRUD
(get, getAllValid, set, update, delete, has, count), KV CRUD (get, set),
and observation patterns. Cross-references svelte skill for fromTable/
fromKv reactive wrappers.
…er packages

Strip tsc --init boilerplate from base (115→32 lines). Update target
to ESNext. Add tsconfig.base.dom.json extending base with DOM and
DOM.Iterable libs for browser-only packages.
…t options

These packages don't use browser DOM APIs—switched from standalone
configs to extending tsconfig.base.json. Removed ~10 options per
package that were already inherited from base.
These options were duplicated in 10/14 child configs. Moving them to
base eliminates the redundancy. Options that conflict with noEmit
(declaration, declarationMap, inlineSources) stay per-package since
library packages must opt into emit individually.
…lat API surface

Removes the nested `actions` sub-object from bookmark, saved-tab,
browser, and filesystem state modules. All mutation methods now live
directly on the returned object, matching the existing pattern in
Honeycrisp (folders, notes, view) and Whispering (deviceConfig, etc.).

Updates all consumer components to drop the `.actions.` accessor.
Adds reactive state module conventions to the svelte skill.
Shared config for packages that emit declarations: noEmit:false,
declaration, declarationMap, inlineSources. Eliminates duplication
across constants, ui, and vault. Also removes redundant module:ESNext
from vault (already inherited from base).
…ir, composite to shared configs

allowJs and allowImportingTsExtensions → base (used by 9 and 5
packages respectively). outDir:dist and composite:true → base.lib
(standard for all library packages). Removes 20+ redundant overrides
across child configs.
Standardizes Bun runtime types across all SvelteKit apps (fuji,
honeycrisp, whispering). Opensidian already had it. Monorepo runs
on Bun so all apps should have the types available.
Resolve conflicts in opensidian components by taking main's new
features (CommandPalette component, inline editing, deleted dialogs)
while preserving our branch's flat API (fsState.selectFile instead
of fsState.actions.selectFile). Flatten all fsState.actions.* refs.
@braden-w braden-w merged commit 60120ef into main Mar 19, 2026
1 of 10 checks passed
@braden-w braden-w deleted the opencode/glowing-pixel branch March 19, 2026 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant